package cn.qio.channel.session;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;

import cn.qio.channel.handler.ChannelHandler;
import cn.qio.event.EventDispatcher;
import cn.qio.event.OrderedEventDispatcher;

public final class SessionServer {

	private EventDispatcher eventDispatcher;

	private final ArrayList<ChannelHandler> eventHandlers = new ArrayList<>();

	private InetSocketAddress inetAddress;

	private ServerSocketChannel ssc;

	private Thread thread;

	private int threadPoolSize = 6;

	private boolean isStarted;

	private boolean isToStop;

	public synchronized void start(int port) throws IOException {
		if (isStarted) {
			return;
		}
		this.inetAddress = new InetSocketAddress(port);
		this.eventDispatcher = new OrderedEventDispatcher(threadPoolSize);
		ssc = ServerSocketChannel.open();
		// ssc.configureBlocking(false);
		ssc.bind(inetAddress);

		this.eventDispatcher.start();
		// 开始接受链接
		thread = new Thread(new AcceptWorker());
		thread.start();
		System.out.println("server start listening at port " + port + " ...");
	}

	class AcceptWorker implements Runnable {

		@Override
		public void run() {
			while (!isToStop) {
				try {
					SocketChannel sc = ssc.accept();
					ChannelSession channelSession = new ChannelSession(sc, eventDispatcher, eventHandlers);
					// 开启一个新的 读写通道
					channelSession.start();
				} catch (IOException e) {
					try {
						Thread.sleep(1000); // 异常后等待一秒
					} catch (InterruptedException e1) {
					}
					e.printStackTrace();
				}
			}
			if (isToStop) {
				System.out.println("server is stopped ...");
			}
		}
	}

	public void ensureNotStarted() {
		if (isStarted) {
			throw new IllegalStateException("event dispacher already started!");
		}
	}

	public void addHandler(ChannelHandler handler) {
		eventHandlers.add(handler);
	}

}
